package per.example.arpproject.utils;

import lombok.Builder;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.io.*;
import java.math.BigInteger;
import java.net.URL;
import java.nio.MappedByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.FileChannel;
import java.nio.channels.ReadableByteChannel;
import java.security.MessageDigest;
import java.text.DecimalFormat;
import java.util.HashMap;
import java.util.Map;


/**
 * 文件公用工具类
 * @author ljh
 * @date 2022-03-18
 */
@Slf4j
@Builder
public class FileTool {

	private static Log fileToolLog = LogFactory.getLog(FileTool.class);

	public static final String UPLOADFILEDIR = "uploadfile";

	public static final String CONTENTFILEDIR = "contentfile";
	
	public static final String EXCELFILEDIR = "excel";

	public static final String MEMBER_DATA = "memberdata";

	public static final String ATTACH_FILE = "attachfile";

	public final static Map<String,String> FILEMIMEMAP = new HashMap<String,String>();

	static {
		FILEMIMEMAP.put("gif", "image/gif");
		FILEMIMEMAP.put("jpg", "image/jpeg");
		FILEMIMEMAP.put("png", "image/png");
		FILEMIMEMAP.put("jpeg", "image/jpeg");
		FILEMIMEMAP.put("bmp", "image/bmp");
		FILEMIMEMAP.put("zip", "application/zip");
		FILEMIMEMAP.put("txt", "text/plain");
		FILEMIMEMAP.put("pdf", "application/pdf");
		FILEMIMEMAP.put("ppt", "appication/powerpoint");
		FILEMIMEMAP.put("doc", "application/msword");
		FILEMIMEMAP.put("docx", "application/msword");
		FILEMIMEMAP.put("xlsx", "application/vnd.ms-excel");
		FILEMIMEMAP.put("xls", "application/vnd.ms-excel");
		FILEMIMEMAP.put("csv", "");
		FILEMIMEMAP.put("rar", "");
	}

	public static boolean createTextFile(String filePath) throws IOException {
		try {
			File file = new File(filePath);
			if (file.exists()) {
				return false;
			}
				
			file.createNewFile();
			return true;
		} catch (Exception e) {
			fileToolLog.info("FileOP createNewFile failed : " + filePath);
			return false;
		}
	}

	public static boolean createFolder(String folderPath) throws IOException {
		try {
			File fd = new File(folderPath);
			if (fd.exists()) {
				return false;
			}
				
			fd.mkdirs();
			return true;
		} catch (Exception e) {
			fileToolLog.info("FileOP CreateFolder failed : " + folderPath);
			return false;
		}
	}

	public static boolean copyFile(String fileName, String fromFolder, String toFolder) {
		FileInputStream fis = null;
		FileOutputStream fos = null;
		try {
			File file = new File(fromFolder + "/" + fileName);
			if (!file.exists()) {
				return false;
			}
				
			File fileDst = new File(toFolder + "/" + fileName);

			File folderDst = new File(toFolder);
			if (!folderDst.exists()) {
				folderDst.mkdirs();
			}
				
			fis = new FileInputStream(file);
			fos = new FileOutputStream(fileDst);
			byte[] buffer = new byte[4096];
			int i = 0;
			while ((i = fis.read(buffer)) != -1) {
				fos.write(buffer, 0, i);
			}
				
			return true;

		} catch (Exception e) {
			// -----------------------------------------
		} finally {
			if (fis != null) {
				try {
					fis.close();
				} catch (IOException e) {
					// -------------------
				}
			}
				
			if (fos != null) {
				try {
					fos.close();
				} catch (IOException e) {
					// -------------------
				}
			}
				
		}
		return false;
	}

	public static boolean copyFile(String fileName, String newFileName,
			String fromFolder, String toFolder) {
		FileInputStream fis = null;
		FileOutputStream fos = null;
		try {
			File file = new File(fromFolder + "/" + fileName);
			if (!file.exists()) {
				return false;
			}
				
			File fileDst = new File(toFolder + "/" + newFileName);

			// if (fileDst.exists()) return false;
			File folderDst = new File(toFolder);
			if (!folderDst.exists()) {
				folderDst.mkdirs();
			}
			
			fis = new FileInputStream(file);
			fos = new FileOutputStream(fileDst);
			byte[] buffer = new byte[4096];
			int i = 0;
			while ((i = fis.read(buffer)) != -1) {
				fos.write(buffer, 0, i);
			}
				
			return true;

		} catch (Exception e) {
			// -----------------------------------------
		} finally {
			if (fis != null) {
				try {
					fis.close();
				} catch (IOException e) {
					// -------------------
				}
			}
				
			if (fos != null) {
				try {
					fos.close();
				} catch (IOException e) {
					// -------------------
				}
			}
				
		}
		return false;
	}

	public static void copyFolder(String fromFolder, String toFolder) {
		try {
			File fd = new File(fromFolder);
			if (!fd.exists()) {
				return;
			}
				
			if (!fd.isDirectory()) {
				return;
			}
				
			File fdDst = new File(toFolder);
			if (!fdDst.exists()) {
				fdDst.mkdirs();
			}
			
			String[] itemList = fd.list();
			if (itemList != null) {
				// int rPos=0;
				for (int i = 0; i < itemList.length; i++) {
					File file = new File(fromFolder + "/" + itemList[i]);
					if (file.isFile()) {
						copyFile(itemList[i], fromFolder, toFolder);
					}
					if (file.isDirectory()) {
						copyFolder(fromFolder + "/" + itemList[i], toFolder
								+ "/" + itemList[i]);
					}
				}
			}

		} catch (Exception e) {
			// -----------------------------------------
		}
	}

	public static void moveFile(String fileName, String fromFolder, String toFolder) {
		if (copyFile(fileName, fromFolder, toFolder)) {
			deleteFile(fromFolder + "/" + fileName);
		}
	}

	
	public static void moveFolder(String folderName, String fromFolder, String toFolder) {

	}

	public static boolean fileExists(String filePath) {
		try {
			File file = new File(filePath);
			if (!file.isFile()) {
				return false;
			}

			if (file.exists()) {
				return true;
			}

		} catch (Exception e) {
			log.error("FileExists error", e);
		}
		return false;
	}

	public static boolean folderExists(String folderPath) {
		try {
			File fd = new File(folderPath);
			if (!fd.isDirectory()) {
				return false;
			}
				
			if (fd.exists()) {
				return true;
			}
				
		} catch (Exception e) {
			log.error("FolderExists error",e);
		}
		return false;
	}

	public static boolean renameFile(String folderPath, String fileName,
			String dstFileName) {
		try {
			File file = new File(folderPath + "/" + fileName);
			File fileNew = new File(folderPath + "/" + dstFileName);
			file.renameTo(fileNew);
			return true;
		} catch (Exception e) {
			log.error("RenameFile error",e);
		}
		return false;
	}

	
	public static boolean renameFolder(String folderPath, String dstFolderPath) {
		try {
			File fd = new File(folderPath);
			if (!fd.isDirectory()) {
				return false;
			}
				
			File fdNew = new File(dstFolderPath);
			if (!fdNew.isDirectory()) {
				return false;
			}
				
			fd.renameTo(fdNew);
			return true;
		} catch (Exception e) {
			log.error("RenameFolder error",e);
		}
		return false;
	}

	public static boolean deleteFile(String filePath) {
		try {
			File file = new File(filePath);
			if (!file.isFile()) {
				return false;
			}
			file.delete();
			return true;
		} catch (Exception e) {
			fileToolLog.info("FileOP delete file failed : " + filePath);
		}
		return false;
	}

	public static boolean deleteFolder(String folderPath) {
		try {
			File fd = new File(folderPath);
			if (!fd.isDirectory()) {
				return false;
			}
				
			fd.delete();
			return true;
		} catch (Exception e) {
			fileToolLog.info("FileOP delete folder failed : " + folderPath);
		}
		return false;
	}

	public static String getFileValue(String filePath) {
		FileReader fr = null;
		String sValue = "";
		File file;
		try {
			file = new File(filePath);
			if (!(file.exists())) {
				return "";
			}
			fr = new FileReader(file);
			char[] c = new char[4096];
			int len;
			while ((len = fr.read(c)) != -1) {
				String s = new String(c, 0, len);
				sValue += s;
			}
			return sValue;
		} catch (IOException ioe) {
		} finally {
			try {
				if (fr != null) {
					fr.close();
				}
			} catch (IOException ioe) {
				// -----------------------------------------
			}
		}
		return "";
	}

	public static void setFileValue(String filePath, String sValue) throws IOException {
		FileOutputStream fos = null;
		try {
			File file = new File(filePath);
			if (!(file.exists())) {
				file.createNewFile();
			}
			fos = new FileOutputStream(file);
			byte[] buffer = sValue.getBytes();
			fos.write(buffer);
		} catch (IOException ioe) {
			// -----------------------------------------
		} finally {
			try {
				if (fos != null) {
					fos.close();
				}
			} catch (IOException ioe) {
				// -----------------------------------------
			}
		}
	}

	public static void saveFile(HttpServletRequest request, InputStream in,
			String realpath) {

		FileOutputStream out = null;
		try {

			out = new FileOutputStream(realpath);
			byte[] buffer = new byte[4096];
			int byteRead = 0;
			while ((byteRead = in.read(buffer)) != -1) {
				out.write(buffer, 0, byteRead);
			}

				

		} catch (FileNotFoundException cnae) {
			throw new RuntimeException(" THE PATH ERROR .".concat(String
					.valueOf(String.valueOf(cnae.getMessage()))));
		} catch (IOException sde) {
			throw new RuntimeException("  IO ERROR !.".concat(String
					.valueOf(String.valueOf(sde.getMessage()))));
		} finally {
			try {
				if (out != null) {
					out.close();
				}
					
				if (in != null) {
					in.close();
				}
				
			} catch (Exception e) {
			}
		}

	}

	public static String[] getItemsOfFolder(String folderPath) {
		try {
			File dir = new File(folderPath);
			if (!dir.isDirectory()) {
				return null;
			}
				
			String[] files = dir.list();
			return files;
		} catch (Exception e) {
			// -----------------------------------------
		}
		return null;

	}

	public static String getFileName(String filePath) {
		int intPos = filePath.lastIndexOf("/");
		if (intPos == -1) {
			intPos = filePath.lastIndexOf("\\");
		}
		if (intPos == -1) {
			return "";
		}
		return filePath.substring(intPos + 1, filePath.length());
	}

	public static long getFileSize(String filePath) {
		try {
			File file = new File(filePath);
			return file.length();
		} catch (Exception e) {
			// -----------------------------------------
		}
		return 0L;
	}
	
	public static String getFileFormetSize(String filePath) {//转换文件大小
	   long fileSize = getFileSize(filePath);
       DecimalFormat df = new DecimalFormat("#.00");
       String fileSizeString = "";
       if (fileSize < 1024) {
           fileSizeString = df.format((double) fileSize) + "B";
       } else if (fileSize < 1048576) {
           fileSizeString = df.format((double) fileSize / 1024) + "K";
       } else if (fileSize < 1073741824) {
           fileSizeString = df.format((double) fileSize / 1048576) + "M";
       } else {
           fileSizeString = df.format((double) fileSize / 1073741824) +"G";
       }
       return fileSizeString;
    }

	public static String getBaseName(String fileName) {
		int intPos = fileName.lastIndexOf(".");
		if (intPos == -1) {
			return fileName;
		}
		return fileName.substring(0, intPos);
	}

	public static String getExtensionName(String fileName) {
		int intPos = fileName.lastIndexOf(".");
		if (intPos == -1) {
			return "";
		}
		return fileName.substring(intPos + 1, fileName.length());
	}

	public static String getFolderName(String folderPath) {
		int intPos = folderPath.lastIndexOf("/");
		if (intPos == -1) {
			intPos = folderPath.lastIndexOf("\\");
		}
		if (intPos == -1) {
			return "";
		}
		return folderPath.substring(intPos + 1, folderPath.length());
	}

	/**
	 * 获取上传文件存放的绝对路径。
	 * 
	 * @return String
	 */
	public static String getFileUploadAbsolutePath(HttpSession session) {
		String dir = File.separator + UPLOADFILEDIR + File.separator
				+ CONTENTFILEDIR + File.separator
				+ DateUtil.getDateString(DateUtil.DATE_PATTERN);
		
		String fullPath = PathUtil.getWebRootPath(session) + dir;

		File path = new File(fullPath);
		if (!path.exists()) {
			path.mkdirs();
		}

		return fullPath;
	}

	/**
	 * 获取上传文件相对web应用根下的存放路径。相对/下的路径。
	 * 
	 * @return
	 */
	public static String getUploadFileDir() {
		String dir = File.separator + UPLOADFILEDIR + File.separator
				+ CONTENTFILEDIR + File.separator
				+ DateUtil.getDateString(DateUtil.DATE_PATTERN);
		String outPutDir = System.getProperty("user.dir")+File.separator+"src"+File.separator+"main"+File.separator+"webapp";
		String fullPath = outPutDir + dir;

		File path = new File(fullPath);
		if (!path.exists()) {
			path.mkdirs();
		}

		return dir;
	}

	public static boolean isRightFile(String fileName, String contentType) {
		String suffixFile = FileTool.getExtensionName(fileName);
		if (!"".equals(contentType)
				&& contentType.equals(FILEMIMEMAP.get(suffixFile))) {
			return true;
		}
		return false;
	}

	public static boolean isRightFile(String fileName) {
		String suffixFile = FileTool.getExtensionName(fileName);
		if (null != FILEMIMEMAP.get(suffixFile)) {
			return true;
		}
		return false;
	}
	
	public static String getFileMd5(File file) throws FileNotFoundException {
		String value = null;
		FileInputStream in = new FileInputStream(file);
		
		try {
			MappedByteBuffer byteBuffer = in.getChannel().map(FileChannel.MapMode.READ_ONLY, 0, file.length());
			MessageDigest md5 = MessageDigest.getInstance("MD5");
			md5.update(byteBuffer);
			BigInteger bi = new BigInteger(1, md5.digest());
			value = bi.toString(16);
		} catch (Exception e) {
			log.error(e.getMessage(),e);
		} finally {
			if (null != in) {
				try {
					in.close();
				} catch (IOException e) {
					log.error(e.getMessage(),e);
				}
			}
		}
		return value;
	}
	
	/**
	 * 删除文件夹及其内文件
	 * 2018年4月23日上午11:01:08
	 * @param folderPath
	 * @author whx
	 */
     public static void delFolderAndFile(String folderPath) {
	     try {
	    	//删除完里面所有内容
	        delAllFile(folderPath); 
	        String filePath = folderPath;
	        filePath = filePath.toString();
	        File myFilePath = new File(filePath);
	        //删除空文件夹
	        myFilePath.delete(); 
	     } catch (Exception e) {
	       log.error(e.getMessage(),e); 
	     }
	}
     

     /**
      * 删除指定文件夹下所有文件
      * @param path 文件夹完整绝对路径
      * @return
      */
      public static boolean delAllFile(String path) {
            boolean flag = false;
            File file = new File(path);
            if (!file.exists()) {
              return flag;
            }
            if (!file.isDirectory()) {
              return flag;
            }
            String[] tempList = file.list();
            File temp = null;
            for (int i = 0; i < tempList.length; i++) {
               if (path.endsWith(File.separator)) {
                  temp = new File(path + tempList[i]);
               } else {
                   temp = new File(path + File.separator + tempList[i]);
               }
               if (temp.isFile()) {
                  temp.delete();
               }
               if (temp.isDirectory()) {
            	   //先删除文件夹里面的文件
                  delAllFile(path + "/" + tempList[i]);
                  //再删除空文件夹
                  delFolderAndFile(path + "/" + tempList[i]);
                  flag = true;
               }
            }
            return flag;
       }

	/**
	 * 根据文件后缀名获取contentType
	 * @param ext 后缀名
	 * @return
	 */
	public static String getContentTypeByExt(String ext){
     		return FILEMIMEMAP.get(ext);
	   }

	  /* *//**
	   *  下载文件通过链接下载文件
	   * @param urlStr 文件的url https://credit.gd.gov.cn/v1/downloadFileAction!downLoadFile.do?attId=206760a9d7864f5989d583a89705f99e
	   * @param filePath 文件路径 D:\DXXWorkSpaceGit\dcboot-gdcredit-parent-2.0\src\main\webapp\/upload/2022/12/21/9cf2ef62afb9431d87bf033df6401600.png
	   * @param compressImg 是否压缩图片
	   * @return: void
	   * @Author: tangfenghan
	   * @Date: 2023/1/19 15:51
	   *//*
		public static void downloadUsingNIO(String urlStr, String filePath,boolean compressImg) throws IOException {
			downloadUsingNIO(urlStr, filePath);
			//判断是否需要压缩
			if(compressImg){
				//判断文件是否为图片文件 后缀为图片
				String suffix = getExtensionName(filePath);
				if(FileUploadValid.checkUploadTypePass(suffix,"image")){
					compressImg(filePath);
				}
			}
		}*/
		/**
		 *  下载文件通过链接下载文件
		 * @param urlStr 文件的url https://credit.gd.gov.cn/v1/downloadFileAction!downLoadFile.do?attId=206760a9d7864f5989d583a89705f99e
		 * @param filePath 文件路径 D:\DXXWorkSpaceGit\dcboot-gdcredit-parent-2.0\src\main\webapp\/upload/2022/12/21/9cf2ef62afb9431d87bf033df6401600.png
		 * @return: void
		 * @Author: tangfenghan
		 * @Date: 2023/1/19 15:51
		 */
		public static void downloadUsingNIO(String urlStr, String filePath) throws IOException {
			URL url = new URL(urlStr);
			ReadableByteChannel rbc = Channels.newChannel(url.openStream());
			//判断文件的文件夹路径是否存在
			createFileDir(filePath);
			FileOutputStream fos = new FileOutputStream(filePath);
			fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
			fos.close();
			rbc.close();
		}

		/**
		*	判断文件的文件夹路径是否存在，不存在是否存在
		* @param filePath 文件全称 D:\DXXWorkSpaceGit\dcboot-gdcredit-parent-2.0\src\main\webapp\/upload/2022/12/21/9cf2ef62afb9431d87bf033df6401600.png
		* @return: void
		* @Author: tangfenghan
		* @Date: 2023/1/19 16:53
		*/
		public static void createFileDir(String filePath){
			int i = filePath.lastIndexOf("/");
			int k = filePath.lastIndexOf("\\");
			int index;
			if(i > k){
				index = i;
			}else{
				index = k;
			}
			String fileDir = filePath.substring(0,index);
			log.info("查询文件夹路径：{}",fileDir);
			File file = new File(fileDir);
			if(!file.exists()){
				file.mkdirs();
			}
		}

		/*private static void compressImg(String fianlFilePath) {
			File syncFile = new File(fianlFilePath);
			try {
				CompressPicUtil.compressPicSmallImg(syncFile);
			} catch (Exception e) {
				log.error("压缩图片失败，地址{}",fianlFilePath);
				log.error(e.getMessage(), e);
			}
			try {
				CompressPicUtil.compressPicTinyImg(syncFile);
			} catch (Exception e) {
				log.error("压缩图片失败，地址{}",fianlFilePath);
				log.error(e.getMessage(), e);
			}
		}*/

		/*public static void main(String[] args) throws IOException {
			System.err.println(System.currentTimeMillis());
			downloadUsingNIO("https://credit.gd.gov.cn/v1/downloadFileAction!downLoadFile.do?attId=206760a9d7864f5989d583a89705f99e","D:\\DXXWorkSpaceGit\\dcboot-gdcredit-parent-2.0\\src\\main\\webapp\\/upload/2022/12/21/9cf2ef62afb9431d87bf033df6401600.png",true);
			System.err.println(System.currentTimeMillis());
		}*/
}